<?php
/**
 *	KLF Framework
 *
 *	Written by Kristian Oye <kristianoye@gmail.com> on Nov 19, 2011
 *	Copyright (C) 2010-2011
 */
namespace KLF\System\Cache
{
	use KLF\System\Cache\KCache;
	use KLF\System\Cache\ICache;
	use KLF\System\Cache\ICacheable;
	use KLF\System\Errors\KFeatureException;
	use KLF\System\Errors\KArgumentException;
	
	/**
	 *  Class KMemcached extends KCache
	 *
	 *  Framework implementation/wrapper for Memcached
	 *
	 *  @package KLF\System\Cache\Memcached
	 *  @access public
	 *  @author Kristian Oye <kristianoye@gmail.com>
	 *  @since 0.1
	 *  
	 *  @see KMemcached::SetValue()
	 *  @see KMemcached::GetValues();
	 *
	 *  @method KMemcache extends KCache NewInstance
	 */
	class KMemcached extends KCache implements ICache
	{
		/**
		 * The underlying Memcache object.
		 * 
		 * @var \Memcache $_rpropMemcached
		 */
		protected $_rpropMemcached;
		
		/**
		 * Constructs a new KMemcache object.
		 * 
		 * @param string $hostname The hostname of the server.
		 * @param integer $port The TCP port the memcached server is located on.
		 * @param unknown_type $timeout The number of seconds to wait for a connection (default of 1).
		 */
		public function __construct($hostname='localhost', $port=11211, $weight = 0, $persistance = NULL)
		{
			if (!extension_loaded('memcached')) {
				throw new KFeatureException('memcached');
			}
			$this->_rpropMemcached = new \Memcached($persistance);
			$this->_rpropMemcached->addServer($hostname, $port, $weight);
		}
		
		/**
		 * Adds a new server to the memcached pool.
		 * 
		 * @param string $hostname The memcached server name.
		 * @param integer $port The port on which the memcached is located.
		 * @param integer $weight The weight given to the new server.  Determines how likely it is to be used.
		 * 
		 * @return KMemcached Returns a reference to the memcache object itself.
		 */
		public function AddServer($hostname, $port, $weight=0)
		{
			$this->_rpropMemcached->addServer(
				$hostname, 
				$port, 
				$weight);
			
			return $this;
		}
		
		/**
		 * Adds a value to the cache.
		 * 
		 * @param string $key The key associated with the value.
		 * @param mixed $val
		 * @param integer $expires
		 * @param integer $flag
		 * 
		 * @return boolean True if successfully added, false if it failed.
		 */
		public function AddValue($key, $val, $expires=0, $flag = NULL)
		{
			return $this->_rpropMemcached->add($key, $val, $flag, $expires);
		}
		
		/**
		 * Deletes values from the cache by using one or more cache keys.
		 *
		 * @author: Kristian Oye <kristianoye@gmail.com>
		 * @since 0.1
		 * @return integer Returns the number of deleted keys.
		*/
		public function DeleteValues()
		{
			$args = func_get_args();
			
			if (count($args) == 0) {
				throw new KArgumentException("Insufficient arguments to DeleteValues()");
			}
			foreach($args as $keyName) {
				$this->_rpropMemcached->delete($keyName);
			}
			return $this;
		}
		
		/**
		 * Clears all the values out of the memcache.
		 * 
		 * @see KLF\System\Cache.ICache::Flush()
		 */
		public function Flush()
		{
			$this->_rpropMemcached->flush();
			
			return $this;
		}
		
		/**
		 * Returns a single value from the cache.
		 * 
		 * @param string $key
		 * @see KLF\System\Cache.ICache::GetValue()
		 * @return mixed
		 */
		public function GetValue($key)
		{
			return $this->_rpropMemcached->get($key);
		}
		
		/**
		 * Returns a set of one or more values from the cache.
		 * 
		 * @see KLF\System\Cache.ICache::GetValues()
		 */
		public function GetValues()
		{
			$args = func_get_args();
			
			if (count($args) == 0) {
				throw new KArgumentException("Insufficient arguments to GetValues()");
			}
			return array_map(function($result) {
				return $result["value"];
			}, $this->_rpropMemcached->getDelayed($args));
		}
		
		/**
		* Initialize the fake cache object.
		 *
		* @see KLF\System\Cache.ICache::Initialize()
		*/
		public function Initialize()
		{
		}
		
		/**
		 * Add or update a value in the cache.
		 * 
		 * @param $key The key associated with the value and used to retrieve it.
		 * @param $val The value to store in the cache.
		 * @param $expires The maximum time the value should live in the cache.
		 * 
		 * @see KLF\System\Cache.ICache::SetValue()
		 */
		public function SetValue($key, $val, $expires = 0)
		{
			$this->_rpropMemcached->set($key, $val, $expires);
			
			return $this;
		}
	}
}
